package jwt

import (
	"errors"
	"time"

	"github.com/dgrijalva/jwt-go"
)

const TokenExpireDuration = time.Hour * 2 //过期时间
var mySecret = []byte("啦啦啦，嘿嘿")           //用于签名的字段；

type MyClaims struct { //username和userID是除官方字段外多加入的字段，别存敏感数据
	UserID             int64  `json:"user_id"`
	Username           string `json:"username"`
	jwt.StandardClaims        //官方设定的各种字段
}

func keyFunc(_ *jwt.Token) (i interface{}, err error) {
	return mySecret, nil
}

// GenToken 生成JWT：包括加密
// GenToken 生成 access token 和 refresh token
// func GenToken(userID int64) (aToken, rToken string, err error) {
func GenToken(userID int64) (string, error) {

	// 创建一个我们自己的声明
	claims := MyClaims{
		UserID: userID, // 自定义字段
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
			Issuer:    "CampusCloudAid",                           // 签发人
		},
	}

	// 生成 access token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(mySecret)
	// 生成 refresh token
	//refreshClaims := jwt.StandardClaims{
	//	ExpiresAt: time.Now().Add(time.Second * 30).Unix(), // 刷新 token 过期时间
	//	Issuer:    "bluebell",                              // 签发人
	//}
	//
	//rToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, refreshClaims).SignedString([]byte(mySecret))
	//if err != nil {
	//	return "", "", err
	//}
	//
	//return aToken, rToken, nil
}

// ParseToken 解析token
// ParseToken 解析JWT
func ParseToken(tokenString string) (*MyClaims, error) { //接收前端传过来的token并解析是否正确
	// 解析token
	var mc = new(MyClaims)

	// 如果是自定义Claim结构体则需要使用 ParseWithClaims 方法
	token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
		// 直接使用标准的Claim则可以直接使用Parse方法
		//token, err := jwt.Parse(tokenString, func(token *jwt.Token) (i interface{}, err error) {
		return mySecret, nil
	})
	if err != nil {
		return nil, err
	}
	// 对token对象中的Claim进行类型断言
	if token.Valid { //校验token
		return mc, nil
	}
	return nil, errors.New("invalid token")
}

// 刷新refresh token
// RefreshToken 刷新 AccessToken
//func RefreshToken(aToken, rToken string) (newAToken, newRToken string, err error) {
//	// Refresh token 无效直接返回
//	if _, err = jwt.Parse(rToken, keyFunc); err != nil {
//		return "", "", err
//	}
//
//	// 从旧 access token 中解析出 claims 数据
//	var claims MyClaims
//	_, err = jwt.ParseWithClaims(aToken, &claims, keyFunc)
//	if err != nil {
//		return "", "", err
//	}
//
//	// 当 access token 是过期错误并且 refresh token 没有过期时就创建一个新的 access token
//	if v, ok := err.(*jwt.ValidationError); ok && v.Errors == jwt.ValidationErrorExpired {
//		return GenToken(claims.UserID)
//	}
//
//	return "", "", errors.New("invalid access token or refresh token")
//}
